﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using MugenInjection.Infrastructure;
using MugenInjection.Wcf.Interface;
using MugenInjection.Web;

namespace MugenInjection.Wcf
{
    /// <summary>
    /// An instance provider that uses MugenInjection to create the instance.
    /// </summary>
    public class MugenInjectionInstanceProvider : IInstanceProvider
    {
        #region Fields

        private readonly Type _serviceType;

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="MugenInjectionInstanceProvider"/> class.
        /// </summary>
        /// <param name="serviceType">Type of the service.</param>
        public MugenInjectionInstanceProvider(Type serviceType)
        {
            Validate.ArgumentNotNull(serviceType, "serviceType");
            _serviceType = serviceType;
        }

        #endregion

        #region Implementation of IInstanceProvider

        /// <summary>
        /// Returns a service object given the specified <see cref="T:System.ServiceModel.InstanceContext"/> object.
        /// </summary>
        /// <returns>
        /// A user-defined service object.
        /// </returns> 
        /// <param name="instanceContext">The current <see cref="T:System.ServiceModel.InstanceContext"/> object.</param>
        public object GetInstance(InstanceContext instanceContext)
        {
            return GetInstance(instanceContext, null);
        }

        /// <summary>
        /// Returns a service object given the specified <see cref="T:System.ServiceModel.InstanceContext"/> object.
        /// </summary>
        /// <returns>
        /// The service object.
        /// </returns>
        /// <param name="instanceContext">The current <see cref="T:System.ServiceModel.InstanceContext"/> object.</param><param name="message">The message that triggered the creation of a service object.</param>
        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            return MugenInjectionHttpApplication.ApplicationConfiguration.Injector.Get(_serviceType);
        }

        /// <summary>
        /// Called when an <see cref="T:System.ServiceModel.InstanceContext"/> object recycles a service object.
        /// </summary>
        /// <param name="instanceContext">The service's instance context.</param><param name="instance">The service object to be recycled.</param>
        public void ReleaseInstance(InstanceContext instanceContext, object instance)
        {
            IReleaseInstanceBehavior releaseInstanceBehavior;
            if (!MugenInjectionHttpApplication.ApplicationConfiguration.Injector.TryGetInto(out releaseInstanceBehavior, WcfConfigExtension.ReleaseInstanceKey, _serviceType))
                return;
            releaseInstanceBehavior.Release(instanceContext, instance);
        }

        #endregion
    }
}